package com.icloud.system.boot.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.icloud.common.cache.service.RedisService;
import com.icloud.common.core.api.ResultCode;
import com.icloud.common.core.constant.AuthConstant;
import com.icloud.common.web.enums.StateEnum;
import com.icloud.common.web.exception.Asserts;
import com.icloud.system.boot.dto.AdminPermissionSaveDto;
import com.icloud.system.boot.mapper.AdminPermissionMapper;
import com.icloud.system.boot.model.AdminPermission;
import com.icloud.system.boot.model.AdminRole;
import com.icloud.system.boot.model.AdminRolePermissionRelation;
import com.icloud.system.boot.service.AdminPermissionService;
import com.icloud.system.boot.service.AdminRolePermissionRelationService;
import com.icloud.system.boot.service.AdminRoleService;
import com.icloud.system.boot.vo.AdminPermissionTreeVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 后台账户权限service 实现类
 */
@Service
public class AdminPermissionServiceImpl extends ServiceImpl<AdminPermissionMapper, AdminPermission> implements AdminPermissionService {

    @Autowired
    private RedisService redisService;
    @Autowired
    private AdminRoleService adminRoleService;
    @Autowired
    private AdminRolePermissionRelationService adminRolePermissionRelationService;


    /**
     * 获取权限角色规则
     */
    @Override
    public Map<Object, Object> getPermissionRolesMap() {
        return redisService.hGetAll(AuthConstant.RESOURCE_ROLES_MAP_KEY);
    }


    /**
     * 添加权限
     */
    @Override
    public void addPermission(AdminPermissionSaveDto dto) {
        //参数补充
        if(dto.getPid() == null) {
            dto.setPid(0L);
        }
        //验证权限类型参数是否有效
        Asserts.fail(dto.getType() != 0 && dto.getType() != 1 && dto.getType() != 2, ResultCode.VALIDATE_FAILED);
        //验证父级权限是否存在
        if(dto.getPid() > 0 && getById(dto.getPid()) == null) {
            Asserts.fail(ResultCode.DATA_NOT_EXISTS);
        }
        //数据插入
        AdminPermission permission = new AdminPermission();
        BeanUtil.copyProperties(dto, permission);
        permission.setState(StateEnum.NORMAL.getCode());
        save(permission);
        //同步权限角色对应关系到redis
        initPermissionRolesMap();
    }

    /**
     * 初始化权限角色规则
     */
    @Override
    public Map<String, List<String>> initPermissionRolesMap() {
        Map<String, List<String>> permissionRolesMap = new TreeMap<>();
        //获取所有角色
        List<AdminRole> roleList = adminRoleService.list(new LambdaQueryWrapper<>());
        //获取所有权限
        List<AdminPermission> permissionList = list(new LambdaQueryWrapper<>());
        //获取所有角色和权限的关系数据
        List<AdminRolePermissionRelation> relationList = adminRolePermissionRelationService.list(new LambdaQueryWrapper<>());
        //循环权限数据，构造每个权限对应的角色信息
        for (AdminPermission permission : permissionList) {
            //过滤出权限对应的角色Id
            Set<Long> roleIds = relationList.stream().filter(item -> Objects.equals(item.getAdminPermissionId(), permission.getId())).map(AdminRolePermissionRelation::getAdminRoleId).collect(Collectors.toSet());
            //将角色id转换成角色 账号类型+id + 角色名称
            List<String> roleNames = roleList.stream().filter(item -> roleIds.contains(item.getId())).map(item -> AuthConstant.ADMIN_CLIENT_ID + "_" + item.getId() + "_" + item.getName()).collect(Collectors.toList());
            permissionRolesMap.put(permission.getValue(), roleNames);
        }
        //将权限角色关系数据更新到redis(先删除，再设置)
        redisService.del(AuthConstant.RESOURCE_ROLES_MAP_KEY);
        redisService.hSetAll(AuthConstant.RESOURCE_ROLES_MAP_KEY, permissionRolesMap);
        return permissionRolesMap;
    }


    /**
     * 删除权限
     */
    @Override
    public void deletePermission(Long permissionId) {
        //删除角色权限关系数据
        adminRolePermissionRelationService.remove(new LambdaQueryWrapper<AdminRolePermissionRelation>().eq(AdminRolePermissionRelation::getAdminPermissionId, permissionId));
        //删除数据
        removeById(permissionId);
        //同步权限角色对应关系到redis
        initPermissionRolesMap();
    }

    @Override
    public List<AdminPermissionTreeVo> getTreePermission(Boolean isIncludeDisable) {
        //获取所有权限
        List<AdminPermission> permissionList  = list(
                new LambdaQueryWrapper<AdminPermission>()
                        .eq(!isIncludeDisable, AdminPermission::getState, StateEnum.NORMAL.getCode())
                        .orderByAsc(AdminPermission::getSort)
        );
        //构造树形数据
        return this.structurePermissionTree(permissionList);
    }

    /**
     * 构造权限树形数据
     */
    private List<AdminPermissionTreeVo> structurePermissionTree(List<AdminPermission> permissionLists) {
        return permissionLists.stream()
                .filter(permission -> permission.getPid().equals(0L))
                .map(permission -> this.covertPermissionToTree(permission, permissionLists))
                .collect(Collectors.toList());
    }

    /**
     * 构造权限树形数据
     */
    private AdminPermissionTreeVo covertPermissionToTree(AdminPermission permission, List<AdminPermission> permissionList) {
        AdminPermissionTreeVo treeVo = new AdminPermissionTreeVo();
        BeanUtils.copyProperties(permission, treeVo);
        List<AdminPermissionTreeVo> children = permissionList.stream()
                .filter(subPermission -> subPermission.getPid().equals(permission.getId()))
                .map(subPermission -> covertPermissionToTree(subPermission, permissionList))
                .collect(Collectors.toList());
        treeVo.setChildren(children);
        return treeVo;
    }


    /**
     * 批量设置权限状态
     */
    @Override
    public void batchSetPermissionStatus(List<Long> permissionIds, String state) {
        //参数校验
        if(CollUtil.isEmpty(permissionIds)) {
            Asserts.fail(ResultCode.VALIDATE_FAILED);
        }
        if(! state.equals(StateEnum.NORMAL.getCode()) && ! state.equals(StateEnum.STOP.getCode())) {
            Asserts.fail(ResultCode.VALIDATE_FAILED);
        }
        //批量更新
        LambdaQueryWrapper<AdminPermission> lqw = new LambdaQueryWrapper<>();
        lqw.in(AdminPermission::getId, permissionIds);

        AdminPermission permission = new AdminPermission();
        permission.setState(state);
        update(permission, lqw);
    }
}
